package com.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.stock.constant.StockConstant;
import com.stock.mapper.SysUserMapper;
import com.stock.pojo.entity.SysUser;
import com.stock.service.UserService;
import com.stock.utils.IdWorker;
import com.stock.vo.req.LoginReqVo;
import com.stock.vo.resp.LoginRespVo;
import com.stock.vo.resp.R;
import com.stock.vo.resp.ResponseCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @description :定义用户服务实现
 */
@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据用户名查询用户信息
     *
     * @param userName
     * @return
     */
    @Override
    public SysUser getUserByUserName(String userName) {

        return sysUserMapper.getUserByUserName(userName);
    }

    /**
     * 用户登录功能
     *
     * @param reqVo
     * @return
     */
    @Override
    public R<LoginRespVo> login(LoginReqVo reqVo) {

        //判断输入参数的合法性
        if (reqVo == null || StringUtils.isBlank(reqVo.getUsername()) || StringUtils.isBlank(reqVo.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }
        //验证码和 sessionID不为空
        if (StringUtils.isBlank(reqVo.getCode()) || StringUtils.isBlank(reqVo.getSessionId())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //1. 获取保存在redis的验证码
        String redisCode = (String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX + reqVo.getSessionId());
        //判断是否过期
        if (StringUtils.isBlank(redisCode)) {
            return R.error(ResponseCode.CHECK_CODE_TIMEOUT);
        }
        //判断验证码是否相等
        if (!StringUtils.equalsIgnoreCase(redisCode, reqVo.getCode())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }


        //根据用户名查询用户信息
        SysUser dbUser = sysUserMapper.getUserByUserName(reqVo.getUsername());
        //判断用户是否存在,判断密码是否正确
        if (dbUser == null || !passwordEncoder.matches(reqVo.getPassword(), dbUser.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }
        //构建响应相对
        LoginRespVo respVo = new LoginRespVo();
        //我们发现respVo与dbUser下具有相同的属性，所以直接复制即可
        //属性名称类型一致
        BeanUtils.copyProperties(dbUser, respVo);
        return R.ok(respVo);
    }

    @Override
    public R<Map> getCaptchaCode() {
        //1. 生成图片验证码
        //参数分别是宽、高、验证码长度、干扰线数量
        LineCaptcha captch = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //获取校验码
        String checkCode = captch.getCode();
        //获取经过base64编码处理的图片数据
        String imageData = captch.getImageBase64();
        //生成sessionID,转化成string，避免前端精度丢失
        String sessionID = String.valueOf(idWorker.nextId());
        //sessionID作为key,校验码作为value保存在redis中,加CK方便以后查询维护
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX+sessionID, checkCode, 5, TimeUnit.MINUTES);

        //组装数据
        Map<String, String> data = new HashMap<>();
        data.put("imageData", imageData);
        data.put("sessionId", sessionID);
        return R.ok(data);

    }
}
